home *** CD-ROM | disk | FTP | other *** search
- ; COMP.S
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Scheme code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Compiler Specific Runtime Routines *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: Terry Caudill Date: Jun 1985 *
- ;* Revision history: *
- ;* - 1 Jun 87: Added PCS-INTEGRATE-DEFINE variable so that MIT style *
- ;* defines don-t expand into named/lambda unless #T. This *
- ;* is a requirement for R^3 Report. (tc) *
- ;* Added STRING->NUMBER & MAKE/STRING as autoload. (tc) *
- ;* Make compiler Re-entrant. (tc) *
- ;* RESET does'nt affect INPUT/OUTPUT-PORT so the system *
- ;* might run in windows other than 'CONSOLE. (rb) *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* - 20 Aug 92: Added support for inline coding (inline-lambda) (lb) *
- ;* - 25 Dec 92: Added Scheme-web support (mv) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
-
- ;
- ; The following functions are related in that they all envoke the
- ; compiler in some form or fashion
- ;
- (define load ; LOAD
- (lambda (filename)
- (let ((read (if (string-ci=? (cadddr (filename-split filename)) ".sw")
- read-sw read))
- (i-port (open-input-file filename)))
- (if (null? i-port)
- (error "Unable to load file" filename)
- (letrec
- ((loop
- (lambda (form)
- (cond ((eof-object? form)
- (close-input-port i-port)
- 'ok)
- (else
- (eval form)
- (loop (read i-port)))))))
- (let ((form (read i-port)))
- (if (eq? form '#!fast-load)
- (begin
- (close-input-port i-port)
- (fast-load filename))
- (loop form))))))))
-
- (define compile-file ; COMPILE-FILE
- (lambda (filename1 filename2)
- (if (or (not (string? filename1))
- (not (string? filename2))
- (equal? filename1 filename2))
- (%error-invalid-operand-list 'COMPILE-FILE
- filename1
- filename2)
- (let ((read (if (string-ci=? (cadddr (filename-split filename1)) ".sw")
- read-sw read))
- (i-port (open-input-file filename1)))
- (let ((o-port (open-output-file filename2)))
- (set-line-length! 74 o-port)
- (letrec
- ((loop
- (lambda (form)
- (if (eof-object? form)
- (begin (close-input-port i-port)
- (close-output-port o-port)
- 'ok)
- (begin ; no COMPILE-FORMS
- (compile-to-file form)
- (set! form '()) ; for GC
- (loop (read i-port))))))
- (compile-to-file
- (lambda (form)
- (let ((cform (compile form)))
- (write (list '%execute (list 'quote cform))
- o-port)
- (newline o-port)
- (%execute cform)))))
- (loop (read i-port))))))))
-
- (define %compile-timings '())
-
- (define %compile ; %COMPILE
- (lambda (exp . time?)
- (when time? (gc))
- (let ((time '())
- (t0 (clock)))
- (set! pcs-local-var-count 0)
- (set! pcs-error-flag #F)
- (set! pcs-verbose-flag (not time?))
- (set! pcs-binary-output #F)
- (set! pme= (pcs-macro-expand exp))
- (if pcs-error-flag
- (error "[Compilation terminated because of errors]")
- (begin
- (set! time (cons (- (clock) t0) time))
- (set! psimp= (pcs-simplify pme=))
- (set! time (cons (- (clock) t0) time))
- (pcs-closure-analysis psimp=)
- (set! time (cons (- (clock) t0) time))
- (set! pcg= (pcs-gencode psimp=))
- (set! time (cons (- (clock) t0) time))
- (set! ppeep= (pcs-postgen pcg=))
- (set! time (cons (- (clock) t0) time))
- (set! pasm= (pcs-assembler ppeep=))
- (set! time (cons (- (clock) t0) time))
- (set! pcs-verbose-flag #F)
- (when time?
- (set! %compile-timings
- (cons (%reverse! time) %compile-timings)))
- pasm=)))))
-
- ;
- ; Make compiler re-entrant (or more so, at any rate). The problem arises
- ; when a macro evokes EVAL and thus COMPILE during macro expansion i9n PME
- ;
- (define compile) ; COMPILE
-
- (let ((ge (%set-global-environment user-global-environment)))
- (set! compile
- (lambda (exp)
- (let* ((vc pcs-local-var-count) ; save
- (vf pcs-verbose-flag)
- (ef pcs-error-flag)
- (bo pcs-binary-output)
- (gensym-string (access string (procedure-environment gensym)))
- (gensym-counter (access counter (procedure-environment gensym)))
- (result (pcs-assembler (pcs-compile-to-AL exp))))
- (set! pcs-local-var-count vc) ; restore
- (set! pcs-verbose-flag vf)
- (set! pcs-error-flag ef)
- (set! pcs-binary-output bo)
- (set! (access string (procedure-environment gensym)) gensym-string)
- (set! (access counter (procedure-environment gensym)) gensym-counter)
- (pcs-clear-registers)
- result)))
- (%set-global-environment ge))
-
- (define pcs-compile-to-AL ; PCS-COMPILE-TO-AL
- (lambda (exp)
- (set! pcs-local-var-count 0)
- (set! pcs-error-flag #F)
- (set! pcs-binary-output #T)
- (set! pcs-verbose-flag #F)
- (let ((t1 (pcs-macro-expand exp)))
- (if pcs-error-flag
- (error "[Compilation terminated because of errors]")
- (begin
- (set! exp '()) ; for GC
- (pcs-clear-registers)
- (let ((t2 (pcs-simplify t1)))
- (pcs-closure-analysis t2)
- (let ((t3 (pcs-gencode t2)))
- (set! t2 '()) ; for GC
- (pcs-clear-registers)
- (let ((t4 (pcs-postgen t3)))
- (pcs-clear-registers)
- t4))))))))
-
- (define pcs-execute-AL ; PCS-EXECUTE-AL
- (lambda (al)
- (let ((t1 (pcs-assembler al)))
- (pcs-clear-registers)
- (%execute t1))))
-
- (define optimize! ; OPTIMIZE!
- (lambda args
- (let ((flag (or (null? args)(car args))))
- (set! pcs-permit-peep-1 flag)
- (set! pcs-permit-peep-2 flag))))
-
-
- ;; Syntax Checking Functions
- ;
- ; These functions may be used by macros and other syntax transformers
- ; to help find violations of Scheme syntax rules. Note that these
- ; check only the syntax, not semantics, of the program fragments they
- ; are defined for. It is the caller's responsibility, for example, to
- ; verify that all of the identifiers bound in a LETREC are distinct.
- ; PCS-CHK-PAIRS can't do so, because it is called to verify pairs for
- ; both LETREC and LET*.
-
- (define pcs-chk-id ; PCS-CHK-ID
- (lambda (e y)
- (when (not (symbol? y))
- (syntax-error "Invalid identifier in expression" y e))))
-
- (define (pcs-chk-length= e y n) ; PCS-CHK-LENGTH=
- (cond ((and (null? y)(zero? n))
- '())
- ((null? y)
- (syntax-error "Expression has too few subexpressions" e))
- ((atom? y)
- (syntax-error (if (atom? e)
- "List expected"
- "Expression ends with `dotted' atom")
- e))
- ((zero? n)
- (syntax-error "Expression has too many subexpressions" e))
- (else
- (pcs-chk-length= e (cdr y) (sub1 n)))))
-
- (define (pcs-chk-length>= e y n) ; PCS-CHK-LENGTH>=
- (cond ((and (null? y)( < n 1))
- '())
- ((atom? y)
- (pcs-chk-length= e y -1))
- (else
- (pcs-chk-length>= e (cdr y) (sub1 n)))))
-
- (define (pcs-chk-bvl e bvl dot-ok?) ; PCS-CHK-BVL
- (letrec ((oops
- (lambda () (syntax-error "Invalid identifier list" e))))
- (cond ((atom? bvl)
- (or (null? bvl)(and dot-ok? (pcs-chk-bvar bvl))
- (oops)))
- ((pcs-chk-bvar (car bvl))
- (pcs-chk-bvl e (cdr bvl) dot-ok?))
- (else
- (oops)))))
-
- (define (pcs-chk-pairs e pairs) ; PCS-CHK-PAIRS
- (letrec ((oops
- (lambda () (syntax-error "Invalid pair binding list" e))))
- (if (atom? pairs)
- (or (null? pairs)
- (oops))
- (let ((pr (car pairs)))
- (if (or (atom? pr)
- (not (pcs-chk-bvar (car pr)))
- (atom? (cdr pr))
- (not (null? (cddr pr))))
- (oops)
- (pcs-chk-pairs e (cdr pairs)))))))
-
-
- (define pcs-chk-bvar ; PCS-CHK-BVAR
- (lambda (id)
- (if (or (not (symbol? id))
- (getprop id 'PCS*MACRO)
- (memq id '(QUOTE LAMBDA IF SET!
- BEGIN LETREC DEFINE)))
- (syntax-error "Invalid bound variable name" id)
- #T)))
-
- ; EXPAND, EXPAND-MACRO and EXPAND-MACRO-1 expand macro calls. EXPAND-MACRO
- ; and EXPAND-MACRO-1 only expand the outer-level form and leave sub-forms
- ; alone. EXPAND-MACRO-1 does so only once, while EXPAND-MACRO does so
- ; repeatedly until there is no change. EXPAND expands form and all subforms
- ; completely.
-
- (define expand-macro ; EXPAND-MACRO
- (lambda (exp)
- (let ((expansion (expand-macro-1 exp)))
- (if (or (atom? exp) (equal? expansion exp))
- expansion
- (expand-macro expansion)))))
-
- (define expand-macro-1 ; EXPAND-MACRO-1
- (lambda (x)
- (cond ((symbol? x)
- (let ((entry (getprop x 'PCS*MACRO)))
- (cond ((null? entry) x)
- ((pair? entry) (if (eq? (car entry) 'ALIAS)
- (cdr entry)))
- ((procedure? entry) (entry x)))))
- ((pair? x)
- (let* ((f (car x))
- (ef (if (pair? f) (expand-macro f) f))
- (a (cdr x)))
- (if (symbol? ef)
- (let ((macfun (getprop ef 'PCS*MACRO)))
- (cond ((null? macfun)
- (cons ef a))
- ((pair? macfun)
- (cons (cdr macfun) a))
- (else
- (macfun (cons ef a)))))
- (cons ef a))))
- (else x))))
-
- (define expand ; EXPAND
- (letrec ((expand-item
- (lambda (item)
- (if (pair? item) (expand item) item))))
- (lambda (exp)
- (let ((expansion (expand-macro exp)))
- (map expand-item expansion)))))
-
- ;
- ; Set up EDWIN so that it may be loaded into its own environment
- ;
-
- (define initiate-edwin ; INITIATE-EDWIN
- (lambda ()
- (unbind 'edwin user-global-environment)
- (set! (access edwin-environment user-global-environment)
- (make-hashed-environment))
- (%reify! edwin-environment 0 user-initial-environment)
- (let ((saved-env (%set-global-environment edwin-environment)))
- (load (%system-file-name "edwin.fsl"))
- (%set-global-environment saved-env))
- (edwin)
- ))
-
- (define edwin initiate-edwin) ; EDWIN
-
- ;
- ; Set up compiler-related global variables
- ;
-
- (BEGIN
- (define %pcs-stl-debug-flag #F)
- (define %pcs-stl-history '(%PCS-STL-HISTORY)) ; getprop tag
- (define pcs-local-var-count 0)
- (define pcs-integrate-integrables #T)
- (define pcs-integrate-primitives #T)
- (define pcs-integrate-define #T)
- (define pcs-debug-mode #F) ; debug mode OFF
- (define pcs-permit-peep-1 #T) ; optimization ON
- (define pcs-permit-peep-2 #T)
- (define pcs-verbose-flag #F)
- (define pcs-display-warnings #T)
- (define pme= '())
- (define psimp= '())
- (define pcg= '())
- (define ppeep= '())
- (define pasm= '())
- )
-
- ; Evaluation
-
- ; EVAL is part interpreter, but calls the compiler for complicated
- ; expressions. In particular, it does not do any bindings
- ; interpretively, since they would have to be first-class
- ; environments and the compiler might be able to do better.
-
- (define eval
- (letrec
- ((eval-exp
- (lambda (xx env)
- (let ((x (expand-macro xx)))
- (if (pair? x)
- (case (car x)
- ((QUOTE) (eval-quote x env))
- ((IF) (eval-if x env))
- ((SET!) (eval-set! x env))
- ((DEFINE) (eval-define x env))
- ((BEGIN) (eval-begin x env))
- ((LET
- LET*
- LETREC
- LAMBDA ) (eval-compile x env))
- ((%%GET-FLUID%%) (eval-fluid x env))
- ((%%SET-FLUID%%) (eval-set-fluid! x env))
- ((THE-ENVIRONMENT) env)
- ((PCS-CODE-BLOCK) (eval-execute x env))
- ((PCS-INLINE-BLOCK) (eval-execute x env))
- (else (eval-application x env)))
- (eval-atom x env)))))
-
- (lookup-binding ; LOOKUP-BINDING
- (lambda (sym)
- ; The following is the object code to lookup/fetch
- ; the binding of sym. It must be passed to %execute with
- ; the desired environment.
- (list 'pcs-code-block 1 4 (list sym)
- '( 7 4 0 ; Ld-global r1,sym
- 59)))) ; exit
-
- (eval-atom ; EVAL-ATOM
- (lambda (x env)
- (cond ((not (symbol? x)) x)
- ((memq x '(#T #F #!TRUE #!FALSE #!UNASSIGNED)) x)
- (else (or (lookup-integrable x env)
- (eval-execute (lookup-binding x) env))))))
-
- (lookup-integrable
- (lambda (x env)
- (let ((info (getprop x 'PCS*PRIMOP-HANDLER)))
- (and info
- (pair? info)
- (eval-exp (cdr info) env)))))
-
- (eval-quote ; EVAL-QUOTE
- (lambda (x env)
- (pcs-chk-length= x x 2)
- (cadr x)))
-
- (eval-id-error
- (lambda (err caller env)
- (syntax-error
- (string-append "Invalid identifier for " caller ": ") err)))
-
-
- (eval-if ; EVAL-IF
- (lambda (x env)
- (if (or (atom? (cdr x)) ; No Pred
- (atom? (cddr x)) ; No Then
- (pair? (cdddr x))) ; has ELSE
- (pcs-chk-length= x x 4)
- (pcs-chk-length= x x 3))
- (cond ((eval-exp (cadr x) env)
- (eval-exp (caddr x) env))
- ((pair? (cdddr x))
- (eval-exp (cadddr x) env))
- (else
- #F))))
-
-
- (set-var-value ; SET-VAR-VALUE
- (lambda (sym value)
- ; The following is the object code code to set the value
- ; of a variable. It must be passed to %execute with the
- ; desired environment.
- (list 'pcs-code-block 2 7 (list sym value)
- '( 1 4 1 ; Load r1, value
- 15 4 0 ; St-glob-env r1,sym
- 59)))) ; exit
-
- (eval-set! ; EVAL-SET!
- (lambda (x env)
- (pcs-chk-length= x x 3)
- (let* ((id (cadr x))
- (var (expand-macro id))
- (value (eval-exp (caddr x) env)))
- (cond ((not (pair? var))
- (cond ((or (not (symbol? var))
- (not (eq? var (expand-macro var))))
- (eval-id-error var "SET!" env))
- ((getprop var 'PCS*PRIMOP-HANDLER)
- ; this is for primitives and define-integrables
- (eval-compile x env))
- (else
- (eval-execute (SET-VAR-VALUE var value) env))))
- (else
- (eval-id-error var "SET!" env))))))
-
- (def-var ; DEF-VAR
- (lambda (sym value)
- ; The following is the object code code to define a variable
- ; in a given environment. It must be passed to %execute with the
- ; desired environment.
- (list 'pcs-code-block 2 7 (list sym value)
- '( 1 4 1 ; Load r1, value
- 31 4 0 ; define! value,sym
- 59)))) ; exit
-
- (eval-define ; EVAL-DEFINE
- (lambda (x env)
- (pcs-chk-length>= x x 3)
- (if (and (pair? (caddr x))
- (memq (caaddr x) '(LAMBDA NAMED-LAMBDA)))
- (eval-compile x env)
- ;else
- (let* ((id (cadr x))
- (var (expand-macro id))
- (value (eval-exp (caddr x) env)))
- (cond ((not (pair? var))
- (cond ((or (not (symbol? var))
- (not (eq? var (expand-macro var))))
- (eval-id-error var "DEFINE" env))
- ((getprop var 'PCS*PRIMOP-HANDLER)
- ; this is for primitives and define-integrables
- (eval-compile x env))
- (else
- (eval-execute (DEF-VAR var value) env)
- id)))
- (else
- (eval-id-error var "DEFINE" env)))))))
-
-
- (eval-begin ; EVAL-BEGIN
- (lambda (x env)
- (pcs-chk-length>= x x 1)
- (let loop ((x (cdr x)))
- (if (null? (cdr x))
- (eval-exp (car x) env)
- (begin
- (eval-exp (car x) env)
- (loop (cdr x)))))))
-
- (lookup-fluid ; LOOKUP-FLUID
- (lambda (sym)
- ; The following is the object code to lookup/fetch the
- ; fluid binding of sym. It must be passed to %execute with
- ; the desired environment.
- (list 'pcs-code-block 1 4 (list sym)
- '( 8 4 0 ; Ld_fl r1,sym
- 59)))) ; exit
-
- (eval-fluid ; EVAL-FLUID
- (lambda (x env)
- (pcs-chk-length= x x 2)
- (eval-execute (lookup-fluid (eval-exp (cadr x) env)) env)))
-
- (set-fluid-var ; SET-FLUID-VAR
- (lambda (sym value)
- ; The following is the object code to set the value of a
- ; fluid variable. It must be passed to %execute with the
- ; desired environment.
- (list 'pcs-code-block 2 7 (list sym value)
- '( 1 4 1 ; Load r1, value
- 16 4 0 ; St-fl r1,sym
- 59)))) ; exit
-
- (eval-set-fluid! ; EVAL-SET-FLUID!
- (lambda (x env)
- (pcs-chk-length>= x x 2)
- (let ((sym (eval-exp (cadr x) env))
- (val (eval-exp (caddr x) env)))
- (pcs-chk-id x sym)
- (eval-execute (set-fluid-var sym val) env))))
-
- (eval-application ; EVAL-APPLICATION
- (lambda (x env)
- (pcs-chk-length>= x x 1)
- (let ((proc (eval-exp (car x) env)))
- (when (not (or (procedure? proc)
- (and (pair? proc)
- (eq? (car proc) 'LAMBDA))))
- (error-procedure "Attempt to call a non-procedural object"
- (cons proc (cdr x))
- env))
- (let ((args (eval-args (cdr x) env)))
- (let* ((saved-env (%set-global-environment env))
- (result (apply proc args)))
- (%set-global-environment saved-env)
- result)))))
-
- (eval-args ; EVAL-ARGS
- (lambda (x env)
- (if (null? x)
- '()
- (cons (eval-exp (car x) env)
- (eval-args (cdr x) env)))))
-
- (eval-compile ; EVAL-COMPILE
- (lambda (x env)
- (eval-execute (compile x) env)))
-
- (eval-execute ; EVAL-EXECUTE
- (lambda (x env)
- (let* ((saved-env (%set-global-environment env))
- (result (%execute x)))
- (%set-global-environment saved-env)
- result)))
-
- ) ; letrec vars
-
- (lambda (exp . rest)
- (let* ((env (cond ((null? rest)
- (let ((e (%set-global-environment
- user-initial-environment)))
- (%set-global-environment e)
- e))
- ((not (environment? (car rest)))
- (%error-invalid-operand 'EVAL (car rest)))
- (else
- (car rest))))
- (result (eval-exp exp env)))
- result))))
-
- (define (inline-lambda count arg)
- (%execute `(pcs-code-block 1 15 (,arg)
- (0 4 0 ; load R1, '()
- 60 4 1 0 ,(if (pair? count) (length count) count)
- ; close R1, |, count
- 59 ; exit
- 1 248 0 ; load-const R62, arg
- 58 248 ; %execute R62
- 59)))) ; exit
-